package cn.zhx.trigger.http;

import cn.zhx.domain.activity.service.IRaffleActivityAccountQuotaService;
import cn.zhx.domain.activity.service.IRaffleActivityPartakeService;
import cn.zhx.domain.strategy.model.entity.RaffleAwardEntity;
import cn.zhx.domain.strategy.model.entity.RaffleFactorEntity;
import cn.zhx.domain.strategy.model.entity.StrategyAwardEntity;
import cn.zhx.domain.strategy.model.valobj.RuleWeightVO;
import cn.zhx.domain.strategy.service.IRaffleAward;
import cn.zhx.domain.strategy.service.IRaffleRule;
import cn.zhx.domain.strategy.service.IRaffleStrategy;
import cn.zhx.domain.strategy.service.armory.IStrategyArmory;
import cn.zhx.trigger.api.IRaffleStrategyService;
import cn.zhx.trigger.api.dto.*;
import cn.zhx.types.enums.ResponseCode;
import cn.zhx.types.exception.AppException;
import cn.zhx.types.model.Response;
import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.dubbo.config.annotation.DubboService;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @Author: zhx
 * @Date: 2024/07/13
 * @Description: 抽奖服务
 **/

@Slf4j
@RestController
@CrossOrigin("${app.config.cross-origin}")
@RequestMapping("/api/${app.config.api-version}/raffle/strategy/")
@DubboService(version = "1.0")
public class RaffleStrategyController implements IRaffleStrategyService {

    @Resource
    private IStrategyArmory strategyArmory;

    @Resource
    private IRaffleAward raffleAward;

    @Resource
    private IRaffleStrategy raffleStrategy;

    @Resource
    private IRaffleRule raffleRule;

    @Resource
    private IRaffleActivityPartakeService raffleActivityPartakeService;

    @Resource
    private IRaffleActivityAccountQuotaService raffleActivityAccountQuotaService;

    /**
     * 策略装配-将信息装配到缓存中
     *
     * @param strategyId 策略id
     * @return 装配结果
     */
    @GetMapping(value = "strategy_armory")
    @Override
    public Response<Boolean> strategyArmory(Long strategyId) {
        try {
            log.info("抽奖策略装配开始: strategyId: {}", strategyId);
            boolean armoryStatus = strategyArmory.assembleLotteryStrategy(strategyId);
            Response<Boolean> response = Response.<Boolean>builder()
                    .code(ResponseCode.SUCCESS.getCode())
                    .info(ResponseCode.SUCCESS.getInfo())
                    .data(armoryStatus)
                    .build();
            log.info("抽奖策略装配完成: strategyId: {} response: {}", strategyId, JSON.toJSONString(response));
            return response;
        } catch (Exception e) {
            log.error("抽奖策略失败: strategyId: {}", strategyId);
            return Response.<Boolean>builder()
                    .code(ResponseCode.UN_ERROR.getCode())
                    .info(ResponseCode.UN_ERROR.getInfo())
                    .build();
        }
    }

    /**
     * 查询奖品列表
     *
     * @param requestDto 请求参数
     * @return 奖品列表
     */
    @PostMapping("query_raffle_award_list")
    @Override
    public Response<List<RaffleAwardListResponseDto>> queryRaffleAwardList(@RequestBody RaffleAwardListRequestDto requestDto) {
        try {
            log.info("抽奖查询奖品列表开始: activityId:{},userId: {}", requestDto.getActivityId(), requestDto.getUserId());
            //1.参数校验
            if (StringUtils.isBlank(requestDto.getUserId()) || null == requestDto.getActivityId()) {
                return Response.<List<RaffleAwardListResponseDto>>builder()
                        .code(ResponseCode.ILLEGAL_PARAMETER.getCode())
                        .info(ResponseCode.ILLEGAL_PARAMETER.getInfo())
                        .build();
            }
            //2.查询奖品配置
            List<StrategyAwardEntity> strategyAwardEntities = raffleAward.queryRaffleStrategyAwardListByActivityId(requestDto.getActivityId());

            //3.获取规则配置 tree_luck_award tree_lock
            String[] treeIds = strategyAwardEntities.stream()
                    .map(StrategyAwardEntity::getRuleModels)
                    .filter(StringUtils::isNotEmpty)
                    .toArray(String[]::new);

            //4.查询规则配置，获取奖品的解锁限制，抽奖N次后解锁 tree_lock_1 ： 10; tree_lock_2 : 20;
            Map<String, Integer> ruleLockCountMap = raffleRule.queryAwardRuleLockCount(treeIds);

            //5.查询抽奖次数 - 用户已经参与的抽奖次数
            Integer dayPartakeCount = raffleActivityPartakeService.queryRaffleActivityAccountDayPartakeCount(requestDto.getActivityId(), requestDto.getUserId());

            //6.遍历填充数据
            List<RaffleAwardListResponseDto> raffleAwardListResponseDtos = strategyAwardEntities.stream()
                    .map(strategyAwardEntity -> {
                        Integer awardRuleLockCount = ruleLockCountMap.get(strategyAwardEntity.getRuleModels());
                        return RaffleAwardListResponseDto.builder()
                                .awardId(strategyAwardEntity.getAwardId())
                                .awardSubTitle(strategyAwardEntity.getAwardSubTitle())
                                .awardTitle(strategyAwardEntity.getAwardTitle())
                                .sort(strategyAwardEntity.getSort())
                                .awardRuleLockCount(awardRuleLockCount)
                                .isAwardUnlock(null == awardRuleLockCount || dayPartakeCount >= awardRuleLockCount)
                                .waitUnLockCount(null == awardRuleLockCount || awardRuleLockCount <= dayPartakeCount ? 0 : awardRuleLockCount - dayPartakeCount)
                                .build();
                    })
                    .collect(Collectors.toList());

            Response<List<RaffleAwardListResponseDto>> response = Response.<List<RaffleAwardListResponseDto>>builder()
                    .code(ResponseCode.SUCCESS.getCode())
                    .info(ResponseCode.SUCCESS.getInfo())
                    .data(raffleAwardListResponseDtos)
                    .build();

            log.info("抽奖查询奖品列表完成: activityId:{},userId: {},response: {}", requestDto.getActivityId(),requestDto.getUserId(), JSON.toJSONString(response));
            return response;
        } catch (Exception e) {
            log.error("抽奖查询奖品列表失败: activityId:{},userId: {}", requestDto.getActivityId(),requestDto.getUserId());
            return Response.<List<RaffleAwardListResponseDto>>builder()
                    .code(ResponseCode.UN_ERROR.getCode())
                    .info(ResponseCode.UN_ERROR.getInfo())
                    .build();
        }
    }




    /**
     * 随机抽奖
     *
     * @param requestDto 请求参数
     * @return 抽奖结果
     */
    @PostMapping("random_raffle")
    @Override
    public Response<RaffleResponseDto> randomRaffle(@RequestBody RaffleRequestDto requestDto) {
        try {
            log.info("随机抽奖开始 strategyId: {}", requestDto.getStrategyId());
            // 调用抽奖接口
            RaffleAwardEntity raffleAwardEntity = raffleStrategy.performRaffle(RaffleFactorEntity.builder()
                    .userId("system")
                    .strategyId(requestDto.getStrategyId())
                    .build());
            // 封装返回结果
            Response<RaffleResponseDto> response = Response.<RaffleResponseDto>builder()
                    .code(ResponseCode.SUCCESS.getCode())
                    .info(ResponseCode.SUCCESS.getInfo())
                    .data(RaffleResponseDto.builder()
                            .awardId(raffleAwardEntity.getAwardId())
                            .awardIndex(raffleAwardEntity.getSort())
                            .build())
                    .build();
            log.info("随机抽奖完成 strategyId: {} response: {}", requestDto.getStrategyId(), JSON.toJSONString(response));
            return response;
        } catch (AppException e) {
            log.error("随机抽奖失败 strategyId：{} {}", requestDto.getStrategyId(), e.getInfo());
            return Response.<RaffleResponseDto>builder()
                    .code(e.getCode())
                    .info(e.getInfo())
                    .build();
        } catch (Exception e) {
            log.error("随机抽奖失败 strategyId：{}", requestDto.getStrategyId(), e);
            return Response.<RaffleResponseDto>builder()
                    .code(ResponseCode.UN_ERROR.getCode())
                    .info(ResponseCode.UN_ERROR.getInfo())
                    .build();
        }
    }


    /**
     * 查询抽奖策略权重配置
     * @param request 用户id + 活动id
     * @return 抽奖策略权重配置
     */
    @PostMapping(value = "query_raffle_strategy_rule_weight")
    @Override
    public Response<List<RaffleStrategyRuleWeightResponseDTO>> queryRaffleStrategyRuleWeight(@RequestBody UserActivityAccountRequestDTO request) {
        try {
            log.info("查询抽奖策略权重规则配置开始 userId:{} activityId：{}", request.getUserId(), request.getActivityId());
            // 1. 参数校验
            if (StringUtils.isBlank(request.getUserId()) || null == request.getActivityId()) {
                throw new AppException(ResponseCode.ILLEGAL_PARAMETER.getCode(), ResponseCode.ILLEGAL_PARAMETER.getInfo());
            }
            // 2. 查询用户抽奖总次数
            Integer userActivityAccountTotalUseCount = raffleActivityAccountQuotaService.queryRaffleActivityAccountPartakeCount(request.getActivityId(), request.getUserId());
            // 3. 查询规则
            List<RaffleStrategyRuleWeightResponseDTO> raffleStrategyRuleWeightList = new ArrayList<>();
            List<RuleWeightVO> ruleWeightVOList = raffleRule.queryAwardRuleWeightByActivityId(request.getActivityId());

            for (RuleWeightVO ruleWeightVO : ruleWeightVOList) {
                // 转换对象
                List<RaffleStrategyRuleWeightResponseDTO.StrategyAward> strategyAwards = new ArrayList<>();
                List<RuleWeightVO.Award> awardList = ruleWeightVO.getAwardList();
                for (RuleWeightVO.Award award : awardList) {
                    RaffleStrategyRuleWeightResponseDTO.StrategyAward strategyAward = new RaffleStrategyRuleWeightResponseDTO.StrategyAward();
                    strategyAward.setAwardId(award.getAwardId());
                    strategyAward.setAwardTitle(award.getAwardTitle());
                    strategyAwards.add(strategyAward);
                }
                // 封装对象
                RaffleStrategyRuleWeightResponseDTO raffleStrategyRuleWeightResponseDTO = new RaffleStrategyRuleWeightResponseDTO();
                raffleStrategyRuleWeightResponseDTO.setRuleWeightCount(ruleWeightVO.getWeight());
                raffleStrategyRuleWeightResponseDTO.setStrategyAwards(strategyAwards);
                raffleStrategyRuleWeightResponseDTO.setUserActivityAccountTotalUseCount(userActivityAccountTotalUseCount);

                raffleStrategyRuleWeightList.add(raffleStrategyRuleWeightResponseDTO);
            }
            //按照RaffleStrategyRuleWeightResponseDTO中的ruleWeightCount进行排序
            raffleStrategyRuleWeightList.sort(Comparator.comparingInt(RaffleStrategyRuleWeightResponseDTO::getRuleWeightCount));

            Response<List<RaffleStrategyRuleWeightResponseDTO>> response = Response.<List<RaffleStrategyRuleWeightResponseDTO>>builder()
                    .code(ResponseCode.SUCCESS.getCode())
                    .info(ResponseCode.SUCCESS.getInfo())
                    .data(raffleStrategyRuleWeightList)
                    .build();
            log.info("查询抽奖策略权重规则配置完成 userId:{} activityId：{} response: {}", request.getUserId(), request.getActivityId(), JSON.toJSONString(response));
            return response;
        } catch (Exception e) {
            log.error("查询抽奖策略权重规则配置失败 userId:{} activityId：{}", request.getUserId(), request.getActivityId(), e);
            return Response.<List<RaffleStrategyRuleWeightResponseDTO>>builder()
                    .code(ResponseCode.UN_ERROR.getCode())
                    .info(ResponseCode.UN_ERROR.getInfo())
                    .build();
        }
    }
}
